<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box">
        <ul>
            <li>1</li>
            <li>2</li>
        </ul>
        
    </div>
    <script>
        ;(function(doc,win){
            let $ = function(selector,context){
                return new init(selector,context)
            }

            ,init = function(selector,context){
                if(!selector){return this}
                let dataTypes = {
                    'string':function(){
                        this.selector = selector;
                        saveDom.call(this,this.queryAll(this.context,selector))
                    }
                    ,'object':function(){
                        saveDom.call(this,selector)
                    }
                    ,'el':function(){
                        this[0] = selector
                        this.length = 1;
                    }
                }
                ,saveDom = function(nodeList){
                    Object.assign(this,nodeList)
                    this.length = nodeList && nodeList.length || 0;
                }
                this.context = context||document;
                dataTypes[selector.nodeType ? 'el' : typeof(selector)].call(this)
                return this;
            }

            $.fn = $.prototype = {
                constructor:$
                ,splice:Array.prototype.splice
                ,queryAll:function(context,selector){
                    return context.querySelectorAll(selector)
                }
                ,isDOM(el){
                    return el.nodeType == (Node.ELEMENT_NODE||Node.DOCUMENT_NODE) || el instanceof $
                }
                ,evtListener:function(event,handle){
                    Array.prototype.forEach.call(this,function(el,i){
                        el.addEventListener(event,handle)
                    })
                    return this;
                }
                //因为click有300ms延迟，为了避免这300ms延迟，就模拟一个click，避免这300ms延迟。
                //300ms延迟原因：想判断用户是双击屏幕还是单击。当用户第一次单击屏幕时，程序会等待300ms判断用户是否再次单击屏幕，若成立则认为是双击屏幕，放大网页。
                ,tap(callback){
                    let sT,eT,sX,sY,eX,eY; 
                    this.evtListener('touchstart',function(e){
                        e.preventDefault();
                        sT = new Date().getTime();
                        sX = e.screenX
                        sY = e.screenY;
                    })
                    this.evtListener('touchend',function(e){
                        eT = new Date().getTime();
                        eX = e.screenX
                        eY = e.screenY;
                        if(eT - sT <= 300 && Math.abs(eX - sX) < 15 && Math.abs(eY - sY) < 15){
                            callback.call(this,e)
                        }
                    })
                }
            }

            init.prototype = $.fn;

            win.$ = $;
        })(document,window);
    </script>
    <script>
        console.log($(document.querySelector("#box")))
        $(document.querySelector("#box")).evtListener('click',function(){
            alert()
        })
    </script>
</body>
</html>